﻿-- Author      : Kurapica

--------------------------
-- MinimapIcon	        --
--------------------------
do
	-- Check Version
	local version = 1

	if not IGAS:RegisterFile("IGAS.GUI.Widget.MinimapIcon", version) then
		return
	end

	local pairs = pairs
	local ipairs = ipairs
	local type = type
	local error = error
    local CreateFrame = IGAS.GUI.CreateFrame

	local _WidgetName = "MinimapIcon"
	local _Base = "Button"

	local _GUI = IGAS.GUI
	local _Widget = IGAS.GUI.Widget
	local _BaseFunc = IGAS.GUI.Base.Func
	local _PropertyType = IGAS.GUI.Base.PropertyType

	-- Script
    local GameTooltip = _BaseFunc.GetWrapper(GameTooltip)
    local Minimap = _BaseFunc.GetWrapper(Minimap)
        
    local minimapShapes = {
        ["ROUND"] = {true, true, true, true},
        ["SQUARE"] = {false, false, false, false},
        ["CORNER-TOPLEFT"] = {true, false, false, false},
        ["CORNER-TOPRIGHT"] = {false, false, true, false},
        ["CORNER-BOTTOMLEFT"] = {false, true, false, false},
        ["CORNER-BOTTOMRIGHT"] = {false, false, false, true},
        ["SIDE-LEFT"] = {true, true, false, false},
        ["SIDE-RIGHT"] = {false, false, true, true},
        ["SIDE-TOP"] = {true, false, true, false},
        ["SIDE-BOTTOM"] = {false, true, false, true},
        ["TRICORNER-TOPLEFT"] = {true, true, true, false},
        ["TRICORNER-TOPRIGHT"] = {true, false, true, true},
        ["TRICORNER-BOTTOMLEFT"] = {true, true, false, true},
        ["TRICORNER-BOTTOMRIGHT"] = {false, true, true, true},
    }
    
    local function updatePosition(button)
        local radius = button.__Position.Radius
        local rounding = button.__Position.Rounding
        local position = button.__Position.MinimapPos
    
        local angle = math.rad(position)
        local x, y, q = math.cos(angle), math.sin(angle), 1
        if x < 0 then q = q + 1 end
        if y > 0 then q = q + 2 end
        local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND"
        local quadTable = minimapShapes[minimapShape]
        if quadTable[q] then
            x, y = x*radius, y*radius
        else
            local diagRadius = math.sqrt(2*(radius)^2)-rounding
            x = math.max(-radius, math.min(x*diagRadius, radius))
            y = math.max(-radius, math.min(y*diagRadius, radius))
        end
        button:SetPoint("CENTER", Minimap, "CENTER", x, y)        
    end

    local function getAnchors(frame)
        local x, y = frame:GetCenter()
        local xFrom, xTo = "", ""
        local yFrom, yTo = "", ""
        if x < GetScreenWidth() / 3 then
            xFrom, xTo = "LEFT", "RIGHT"
        elseif x > GetScreenWidth() / 3 then
            xFrom, xTo = "RIGHT", "LEFT"
        end
        if y < GetScreenHeight() / 3 then
            yFrom, yTo = "BOTTOM", "TOP"
            return "BOTTOM"..xFrom, "TOP"..xTo
        elseif y > GetScreenWidth() / 3 then
            yFrom, yTo = "TOP", "BOTTOM"
        end
        local from = yFrom..xFrom
        local to = yTo..xTo
        return (from == "" and "CENTER" or from), (to == "" and "CENTER" or to)
    end
        
    local function OnEnter(self, ...)        
        local from, to
        from, to = getAnchors(self)
        
        GameTooltip:SetOwner(self, "ANCHOR_NONE")
        GameTooltip:ClearAllPoints()
        GameTooltip:SetPoint(from, self, to, 0, 0)
        if self.Tooltip ~= "" then
            GameTooltip:SetText(self.Tooltip)
        end
        self:Fire("OnGameTooltipShow")
        GameTooltip:Show()
    end
    
    local function OnLeave(self, ...)        
        GameTooltip:Hide()
    end

    local function OnMouseDown(self, ...)        
        self:GetChild("Icon"):SetTexCoord(0, 1, 0, 1)
    end
    
    local function OnMouseUp(self, ...)         
        self:GetChild("Icon"):SetTexCoord(0.05, 0.95, 0.05, 0.95)
    end
    
    local function OnUpdate(self)
        local mx, my = Minimap:GetCenter()
        local px, py = GetCursorPosition()
        local scale = Minimap:GetEffectiveScale()
        px, py = px / scale, py / scale
        self.__Position.MinimapPos = math.deg(math.atan2(py - my, px - mx)) % 360
        updatePosition(self)
    end
    
    local function OnDragStart(self, ...)        
        self:LockHighlight()
        self:GetChild("Icon"):SetTexCoord(0, 1, 0, 1)
        self.OnUpdate = OnUpdate
        GameTooltip:Hide()
    end
    
    local function OnDragStop(self, ...)        
        self.OnUpdate = nil
        self:GetChild("Icon"):SetTexCoord(0.05, 0.95, 0.05, 0.95)
        self:UnlockHighlight()
        
        self:Fire("OnPositionChanged")
    end
        
	-- ScriptType
	local _ScriptType = {
        ["OnPositionChanged"] = true,
        ["OnGameTooltipShow"] = true,
	}
		
	--	FuncProxy
	local _FuncProxy = {
        -- SetIcon
        ["SetIcon"] = function(self, icon)
            self:GetChild("Icon"):SetTexture(icon)
        end,
	}

	--	Property
	local _Property = {
        -- Tooltip
        ["Tooltip"] = {
            ["Set"] = function(self, tooltip)
                self.__Tooltip = tostring(tooltip or "")
            end,
            ["Get"] = function(self)
                return self.__Tooltip or ""
            end,
            ["Type"] = _PropertyType.String,
        },
        -- ["Position"]
        ["Position"] = {
            ["Set"] = function(self, position)
                if position and type(position) == "table" and 
                    position["Radius"] and type(position["Radius"]) == "number" and
                    position["Rounding"] and type(position["Rounding"]) == "number" and
                    position["MinimapPos"] and type(position["MinimapPos"]) == "number" then
                    self.__Position["Radius"] = position["Radius"]
                    self.__Position["Rounding"] = position["Rounding"]
                    self.__Position["MinimapPos"] = position["MinimapPos"]
                    updatePosition(self)
                else
                    error("The parameter must be a table that contains Radius,Rounding and MinimapPos with number values", 2)
                end
            end,
            ["Get"] = function(self)
                return {["Radius"] = self.__Position["Radius"],
                        ["Rounding"] = self.__Position["Rounding"],
                        ["MinimapPos"] = self.__Position["MinimapPos"],
                        }
            end,
            ["Type"] = _PropertyType.MiniMapPosition,
        },
	}

	local function _New(parent)		
		local button = CreateFrame("Button", nil, Minimap)
        
        -- Remove it make it free to set name
        Minimap:RemoveChild(button)
        
        button:SetFrameStrata("MEDIUM")
        button:SetWidth(31)
        button:SetHeight(31)
        button:SetFrameLevel(8)
        button:RegisterForClicks("anyUp")
        button:RegisterForDrag("LeftButton")
        button:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
        
        local overlay = CreateFrame("Texture", "OverLay", button, "OVERLAY")
        overlay:SetWidth(53)
        overlay:SetHeight(53)
        overlay:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder")
        overlay:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0)
        
        local icon = CreateFrame("Texture", "Icon", button, "BACKGROUND")
        icon:SetWidth(20)
        icon:SetHeight(20)
        icon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
        icon:SetPoint("TOPLEFT", button, "TOPLEFT", 7, -5)
        
        button.__Position = {
            ["Radius"] = 80,
            ["Rounding"] = 10,
            ["MinimapPos"] = random(0, 360),
        }
                
        updatePosition(button)
        
        button:StackScript("OnEnter", OnEnter)
        button:StackScript("OnLeave", OnLeave)
        button:StackScript("OnDragStart", OnDragStart)
        button:StackScript("OnDragStop", OnDragStop)
        button:StackScript("OnMouseDown", OnMouseDown)
        button:StackScript("OnMouseUp", OnMouseUp)
    
		return button
	end	

	-- Register
	local _WidgetInfo = {
		["WidgetName"] = _WidgetName,
		["Base"] = _Base,
		["FuncProxy"] = _FuncProxy,
		["Property"] = _Property,
		["ScriptType"] = _ScriptType,
		["New"] = _New,
        ["NotChild"] = true,
	}

	_Widget[_WidgetName] = _GUI.NewWidget(_WidgetInfo)
end
